# -*- coding: utf-8 -*-
"""
条件验证
Date: 2018-11-23
Author: Likejian
"""
import attr
from itertools import chain

from pyshare.const.enums.cross_siegelord_enum import CrossSiegelordShopBuyType, CrossSiegelordShopLimitType
from pyshare.framework.error_handle import GameException, CrossGameException

from pyshare.utils.time_utils import getCT
from pyshare.const.enums.harem import PalaceState
from pyshare.const.lang.tips_info import TipsInfo
import itertools


class Validation(object):
    def __init__(self, pushedback, func):
        self.func = func
        self.pushedback = pushedback
        _ = self.do

    @property
    def generator(self):
        return self.func(self.pushedback)

    @property
    def do(self):
        for _ in self.generator:
            pass
        return

    def add_validator(self, val):
        self.pushedback = []
        self.pushedback.extend(val)
        _ = self.do
        # return self.generator


def validation(validators):
    for v in validators:
        v.validate()


def validation_v2(validators):
    """ Generator """
    for v in validators:
        yield v.validate()


def jump_iter_location(iterator, start, end):
    for _ in itertools.islice(iterator, start, end):
        pass


class ValidatorException(GameException):
    pass


####### 角色属性 ########
@attr.s(frozen=True, hash=False, repr=True)
class EnoughVipLvValidator(object):
    """ 足够的vip等级 """
    role = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if self.role.vip_lv < self.min_val:
            raise ValidatorException(TipsInfo.RoleKeys.vipLvNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughRoleLvValidator(object):
    """ 足够的角色等级 """
    role = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if self.role.role_lv < self.min_val:
            raise ValidatorException(TipsInfo.RoleKeys.roleLvNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughTotalLoginDayValidator(object):
    """ 足够的累计登陆天数 """
    total_login_day = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if self.total_login_day < self.min_val:
            raise ValidatorException(TipsInfo.RoleKeys.sequentLoginDayNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughComprehensiveValidator(object):
    """ 足够的国力 """
    indicate = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if self.indicate.comprehensive < self.min_val:
            raise ValidatorException(TipsInfo.RoleKeys.comprehensiveNotEnough)


####### 后宫妃子 ########
@attr.s(frozen=True, hash=False, repr=True)
class ConcubineOwnerValidator(object):
    """ 没有该妃子 """
    concubine = attr.ib()

    def validate(self):
        if not self.concubine:
            raise ValidatorException(
                TipsInfo.ConcubineKeys.missConcubine
            )


@attr.s(frozen=True, hash=False, repr=True)
class EnoughConcubineIntimateLvValidator(object):
    """ 妃子足够的亲密等级 """
    concubine = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if self.concubine.intimate_lev < self.min_val:
            raise ValidatorException((
                TipsInfo.ConcubineKeys.intimateLvNotEnough,
                self.min_val
            ))


@attr.s(frozen=True, hash=False, repr=True)
class EnoughConcubineValidator(object):
    """ 足够的妃子数 """
    concubines = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if len(self.concubines) < self.min_val:
            raise ValidatorException(TipsInfo.ConcubineKeys.notEnoughConcubines)


####### 宫殿建造 ########

@attr.s(frozen=True, hash=False, repr=True)
class PalaceUnbuildValidator(object):
    """ 宫殿未建造 """
    palace = attr.ib()

    def validate(self):
        if self.palace.palace_state != PalaceState.Unbuild:
            raise ValidatorException(TipsInfo.Palace.palaceCantBeBuilt)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceUnderConstructionValidator(object):
    """ 宫殿建造中 """
    palace = attr.ib()

    def validate(self):
        if self.palace.palace_state != PalaceState.UnderConstruction:
            raise ValidatorException(TipsInfo.Palace.palaceCantBeFinish)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceFinishConstructionValidator(object):
    """ 宫殿建造完成 """
    palace = attr.ib()

    def validate(self):
        if self.palace.palace_state != PalaceState.FinishConstruction:
            raise ValidatorException(TipsInfo.Palace.palaceUnbuilt)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceCompleteTimeHasNotPassedValidator(object):
    """ 宫殿未达到完成建造时间 """
    palace = attr.ib()

    def validate(self):
        if self.palace.built_complete_time <= getCT():
            raise ValidatorException(TipsInfo.Palace.palaceCompleteTimeHasPassed)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceCompleteTimeHasPassedValidator(object):
    """ 宫殿已达到完成建造时间 """
    palace = attr.ib()

    def validate(self):
        if self.palace.built_complete_time > getCT():
            raise ValidatorException(TipsInfo.Palace.palaceCompleteTimeHasNotPassed)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceBelowMaxLvValidator(object):
    """ 宫殿未达到最高等级 """
    palace = attr.ib()
    max_lv = attr.ib()

    def validate(self):
        if self.palace.palace_lv >= self.max_lv:
            raise ValidatorException(TipsInfo.Palace.palaceIsMaxLv)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceConcubineHasResideValidator(object):
    """ 妃子已经入住在某个宫殿中 """
    palaces = attr.ib()
    concubine_id = attr.ib()

    def validate(self):
        for p in self.palaces:
            if p.concubine_id == self.concubine_id:
                raise ValidatorException(TipsInfo.Palace.palaceConcubineHasReside)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceChangeIsCoolDownValidator(object):
    """ 宫殿换妃子冷却时间 """
    partial_palace = attr.ib()
    palace_role = attr.ib()
    cd_time = attr.ib()

    def validate(self):
        if not self.palace_role.reside_is_cooldown(self.cd_time) and self.partial_palace.is_reside():
            raise ValidatorException(TipsInfo.Palace.palaceIsCoolingDown)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughPalacePopularityValidator(object):
    """ 足够的宫殿人气 """
    palace = attr.ib()
    min_popularity = attr.ib()

    def validate(self):
        if self.palace.popularity < self.min_popularity:
            raise ValidatorException(TipsInfo.Palace.palacePopularityNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughHaremForPalaceAssignValidator(object):
    """ 足够的宫女被赏赐 """
    palace_role = attr.ib()
    harem_id = attr.ib()
    min_val = attr.ib()

    def validate(self):
        if not self.palace_role or \
                self.palace_role.get_harem_num(self.harem_id) < self.min_val:
            raise ValidatorException(TipsInfo.Palace.palaceHaremNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceHaveNotDinnerDressValidator(object):
    """ 未拥有该装扮 """
    palace_role = attr.ib()
    dress_id = attr.ib()

    def validate(self):
        if self.dress_id in self.palace_role.dinner_dress_list:
            raise ValidatorException(TipsInfo.Palace.palaceHaveDinnerDress)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceHaveDinnerDressValidator(object):
    """ 拥有该装扮 """
    palace_role = attr.ib()
    dress_id = attr.ib()

    def validate(self):
        if self.dress_id not in self.palace_role.dinner_dress_list:
            raise ValidatorException(TipsInfo.Palace.palaceHaveNotDinnerDress)


@attr.s(frozen=True, hash=False, repr=True)
class PartialPalaceUnlockedConstructionValidator(object):
    """ 配殿已解锁 """
    partial_palace = attr.ib()

    def validate(self):
        if not self.partial_palace:
            raise ValidatorException(TipsInfo.Palace.PartialPalaceNotUnlock)


@attr.s(frozen=True, hash=False, repr=True)
class PartialPalaceNotUnlockedConstructionValidator(object):
    """ 配殿未解锁 """
    partial_palace = attr.ib()

    def validate(self):
        if self.partial_palace:
            raise ValidatorException(TipsInfo.Palace.PartialPalaceAlreadyUnlock)


@attr.s(frozen=True, hash=False, repr=True)
class EnoughPalaceLvValidator(object):
    """ 足够的宫殿等级 """
    palace = attr.ib()
    profile = attr.ib()

    def validate(self):
        if self.palace.palace_lv < self.profile.NeedPalaceLv:
            raise ValidatorException(TipsInfo.Palace.PalaceLvNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceHaveNotCostumeValidator(object):
    """ 未拥有该宫殿皮肤 """
    palace = attr.ib()
    costume_id = attr.ib()

    def validate(self):
        if self.costume_id in self.palace.palace_costume_list:
            raise ValidatorException(TipsInfo.Palace.PalaceAlreadyHaveCostume)


@attr.s(frozen=True, hash=False, repr=True)
class PalaceHaveCostumeValidator(object):
    """ 已拥有该宫殿皮肤 """
    palace = attr.ib()
    costume_id = attr.ib()

    def validate(self):
        if self.costume_id != 0 and (self.costume_id not in self.palace.palace_costume_list):
            raise ValidatorException(TipsInfo.Palace.PalaceNotHaveCostume)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordGoodsValidator(object):
    """ 商铺商品是否存在 """
    shop = attr.ib()

    def validate(self):
        if not self.shop:
            raise CrossGameException(TipsInfo.RoleKeys.configError)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordRoleValidator(object):
    """ 攻城略地角色是否存在 """
    siegelord_role = attr.ib()

    def validate(self):
        if not self.siegelord_role:
            raise CrossGameException(TipsInfo.RoleKeys.configError)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordShopCfgValidator(object):
    """ 远征普通商铺是否存在 """
    shop_records = attr.ib()

    def validate(self):
        if not self.shop_records:
            raise CrossGameException(TipsInfo.RoleKeys.configError)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordGiftShopCfgValidator(object):
    """ 远征高级商铺是否存在 """
    gift_records = attr.ib()

    def validate(self):
        if not self.gift_records:
            raise CrossGameException(TipsInfo.RoleKeys.configError)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordRoleShopRecordValidator(object):
    """ 远征商铺玩家记录是否存在 """
    role_buy_record = attr.ib()

    def validate(self):
        if not self.role_buy_record:
            raise CrossGameException(TipsInfo.RoleKeys.configError)


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordGoodLimitValidator(object):
    """ 商品是否限购 """
    shop = attr.ib()
    gift_buy_stat = attr.ib()
    count = attr.ib()

    def validate(self):
        today_buy_count = self.gift_buy_stat.get("TodayBuyCount", 0)
        buy_count = self.gift_buy_stat.get("BuyCount", 0)

        old_count = today_buy_count if self.shop.limit_type == CrossSiegelordShopLimitType.DailyLimit else buy_count
        if old_count + self.count > self.shop.limit_times:
            raise CrossGameException("超出购买数量")


@attr.s(frozen=True, hash=False, repr=True)
class SiegelordGoodNeedCostNumValidator(object):
    """ 购买道具所需消耗数量是否足够 """
    siegelord_role = attr.ib()
    shop = attr.ib()
    count = attr.ib()
    res_manager = attr.ib()

    def validate(self):
        if self.shop.buy_type == CrossSiegelordShopBuyType.Coin:
            if self.siegelord_role.coin < self.shop.cost_num * self.count:
                raise CrossGameException("货币数量不足")
        elif self.shop.buy_type == CrossSiegelordShopBuyType.Gold:
            if self.res_manager.get_gamegold() < self.shop.cost_num * self.count:
                raise CrossGameException(TipsInfo.ResourceKeys.GoldsNotEnough)


@attr.s(frozen=True, hash=False, repr=True)
class CashGiftAmountValidator(object):
    """ 现金礼包金额是否一致  """
    gift = attr.ib()
    amount = attr.ib()

    def validate(self):
        if self.gift.amount != self.amount:
            raise CrossGameException("金额不一致")
